

#ifndef __COMM_GEOMETRY_H__
#define __COMM_GEOMETRY_H__

#include "comm/comm_base.h"
#include <iostream>
#include <list>
#include <vector>

using namespace std;

/**************************************************************************************
功能描述: 向量
修改记录:
**************************************************************************************/
class VECTOR_C
{
public:
    VECTOR_C(void);
    VECTOR_C(const COORDINATE_2D_STRU &stStartPoint, const COORDINATE_2D_STRU &stEndPoint);
    VECTOR_C(float len, float dirAngle);

    /* 判断方向是否一样 */
    BOOL  IsDirSame(const VECTOR_C &objOther) const;

    /* 判断方向是否一致，即夹角小于90° */
    BOOL  IsDirConsistent(VECTOR_C &objOther);

    /* 获取两向量夹角 */
    float GetIncludedAngle(const VECTOR_C &objOther) const;

    /* 获取向量长度 */
    float GetLen(void) const;

    float GetDirAngle(void);

    float GetLenSqu(void) const;

    /* 获取点乘 */
    float DotMult(VECTOR_C &objOther);

private:
    BOOL               isValid_;

    BOOL               isExistPoint_;
    COORDINATE_2D_STRU stPoint_;

    BOOL               isExistDirLen_;
    float              len_;
    float              dirAngle_;

    inline void ToPoint(void)
    {
        stPoint_.x = len_ * cos(dirAngle_);
        stPoint_.y = len_ * sin(dirAngle_);

        isExistPoint_ = true;
    }

    inline void ToDirLen(void)
    {
        len_      = sqrt(stPoint_.x * stPoint_.x + stPoint_.y * stPoint_.y);
        dirAngle_ = atan2(stPoint_.y, stPoint_.x);

        isExistDirLen_ = true;
    }
};

/**************************************************************************************
功能描述: 有向直线
          采用一个点和一个向量来表示
修改记录:
**************************************************************************************/
class DIRECTED_LINE_C
{
public:
    DIRECTED_LINE_C(void);
    DIRECTED_LINE_C(const COORDINATE_2D_STRU &stStartPoint, const COORDINATE_2D_STRU &stEndPoint);
    DIRECTED_LINE_C(const COORDINATE_2D_STRU &stStartPoint, float dirAngle);

    void  Reset(const COORDINATE_2D_STRU &stStartPoint, const COORDINATE_2D_STRU &stEndPoint);
    void  Reset(const COORDINATE_2D_STRU &stEndPoint);
    void  Reset(const COORDINATE_2D_STRU &stStartPoint, float dirAngle);
    void  Reset(const COORDINATE_2D_STRU &stStartPoint, float dirAngleSin, float dirAngleCos);
    void  Clear(void);

    BOOL  IsValid(void) const;
    bool  IsPointOnLeft(const COORDINATE_2D_STRU &stPoint) const;
    bool  IsPointOnLine(const COORDINATE_2D_STRU &stPoint) const;
    bool  IsPointOnRight(const COORDINATE_2D_STRU &stPoint) const;

    int   GetIntersectionWithAnotherLine(const DIRECTED_LINE_C &objLine2, COORDINATE_2D_STRU &stIntersection) const;
    float GetDistSquToPoint(const COORDINATE_2D_STRU &stPoint) const;
    float GetDirAngle(void) const;

protected:
    COORDINATE_2D_STRU stStartPoint_;

private:
    COORDINATE_2D_STRU stVector_;

    void  GetVector(const COORDINATE_2D_STRU &stPoint1, const COORDINATE_2D_STRU &stPoint2, COORDINATE_2D_STRU &stVector) const;
    float GetPointVectorCrossMulti(const COORDINATE_2D_STRU &stPoint) const;
};

/**************************************************************************************
功能描述: 射线
修改记录:
**************************************************************************************/
class RAY_C : public DIRECTED_LINE_C
{
public:
    RAY_C(const COORDINATE_2D_STRU &stStartPoint, const COORDINATE_2D_STRU &stForwardPoint)
          : DIRECTED_LINE_C(stStartPoint, stForwardPoint)    {
    }

    RAY_C(const COORDINATE_2D_STRU &stPoint, float dirAngle)
          : DIRECTED_LINE_C(stPoint, dirAngle)    {
    }

    const COORDINATE_2D_STRU &GetStartPoint(void) const;

protected:
private:
};

/**************************************************************************************
功能描述: 有向线段
修改记录:
**************************************************************************************/
class DIRECTED_LINE_SEGMENT_C : public RAY_C
{
public:
    DIRECTED_LINE_SEGMENT_C(const COORDINATE_2D_STRU &stStartPoint, const COORDINATE_2D_STRU &stEndPoint)
                           : RAY_C(stStartPoint, stEndPoint)
    {
        stEndPoint_.Copy(stEndPoint);
    }

    const COORDINATE_2D_STRU &GetEndPoint(void) const;
    bool IsIntersectedWithRay(const RAY_C &objRay) const;
    int  GetIntersectionWithRay(const RAY_C &objRay, COORDINATE_2D_STRU &stIntersection) const;

    BOOL IsIntersectedWithOtherLineSeg(const DIRECTED_LINE_SEGMENT_C &objOther) const;

private:
    COORDINATE_2D_STRU stEndPoint_;
};

/**************************************************************************************
功能描述: 多段有向直线
          有序的多个点，两两依次组成多个有向直线
          处理多边形时，仅用于处理凸多边形
修改记录:
**************************************************************************************/
class MULT_DIRECTED_LINE_C
{
public:
    MULT_DIRECTED_LINE_C(void);
    ~MULT_DIRECTED_LINE_C(void);

    void AddExtendPoint(const COORDINATE_2D_STRU &stNewPoint);
    void AddExtendPoint(float pointX, float pointY);
    void Clear(void);
    bool IsPointOnLeft(const COORDINATE_2D_STRU &stPoint);

protected:

private:
    bool isFirstPointExist_;
    COORDINATE_2D_STRU stLastPoint_;
    list<DIRECTED_LINE_C *> lstDirLine_;
};

/**************************************************************************************
功能描述: 任意多边形
修改记录:
**************************************************************************************/
class ANY_POLYGON_C
{
public:
    ANY_POLYGON_C(const COORDINATE_2D_STRU astPoint[], UINT32 pointNum)
    {
        INT32 rslt = Reset(astPoint, pointNum);
        if (rslt != 0) {
            ST_LOG_ERR("Reset() Fail.");
        }
    }

    ANY_POLYGON_C(void)
    {
    }

    BOOL  IsValid(void) const;
    BOOL  IsPointIn(const COORDINATE_2D_STRU &stPoint) const;
    INT32 Reset(const COORDINATE_2D_STRU astPoint[], UINT32 pointNum);

private:
    bool                            isExistFirstVertice_;            /* 临时变量，是否已存在第一个顶点 */
    COORDINATE_2D_STRU              stLastVertice_;                  /* 临时变量，上次添加的顶点 */
    vector<DIRECTED_LINE_SEGMENT_C> vectDirSide_;

    BOOL  IsNewSideValid(const DIRECTED_LINE_SEGMENT_C &objNewSide, BOOL isLastSide) const;
    INT32 AddVertice(const COORDINATE_2D_STRU &stPoint, BOOL isLastPoint);
    void  DspAllVertice(const COORDINATE_2D_STRU astPoint[], UINT32 pointNum) const;
    INT32 Make(const COORDINATE_2D_STRU astPoint[], UINT32 pointNum);
    void  Clear(void);
};

/**************************************************************************************
功能描述: 凸多边形
          给定的多边形定点合法性由调用方保证
修改记录:
**************************************************************************************/
class CONVEX_POLYGON_C
{
public:
    CONVEX_POLYGON_C(COORDINATE_2D_STRU astPoint[], int pointNum);
    CONVEX_POLYGON_C(void);
    ~CONVEX_POLYGON_C(void);

    int Reset(COORDINATE_2D_STRU astPoint[], int pointNum);

    bool  IsPointIn(const COORDINATE_2D_STRU &stPoint) const;

    float GetDistSquOfInternalPointAlongDirToEdge(const COORDINATE_2D_STRU &stInternalPoint, float dirAngle);
    float GetMinDistSquOfInternalPointToEdge(const COORDINATE_2D_STRU &stInternalPoint);

private:
    bool               isExistFirstVertice_;            /* 临时变量，是否已存在第一个顶点 */
    COORDINATE_2D_STRU stLastVertice_;                  /* 临时变量，上次添加的顶点 */
    list<DIRECTED_LINE_SEGMENT_C *> lstDirLineSeg_;

    int  AddVertice(COORDINATE_2D_STRU &stPoint);
    bool IsValid(void);
    void Clear(void);
    int  Make(COORDINATE_2D_STRU astPoint[], int pointNum);

    DIRECTED_LINE_SEGMENT_C *GetLineSegIntersectedByInternalRay(RAY_C &objInternalRay);
};

/**************************************************************************************
功能描述: 三角形
修改记录:
**************************************************************************************/
class TRIANGLE_C
{
public:
    float Get3thSideLenSqu(float sideLen1, float sideLen2, ANGLE_C &objAngleOf2Sides);
private:
};

/**************************************************************************************
功能描述: 圆形
修改记录:
**************************************************************************************/
class CIRCULAR_C
{
public:
    CIRCULAR_C(const COORDINATE_2D_STRU &stCenter, float radius);
    CIRCULAR_C(const COORDINATE_2D_STRU &stPoint1, const COORDINATE_2D_STRU &stPoint2, const COORDINATE_2D_STRU &stPoint3);

    BOOL  IsValid(void) const;
    INT32 GetCenter(COORDINATE_2D_STRU &stCenter) const;
    float GetRadiusSqu(void) const;
    float GetRadius(void);
    INT32 GetSamplePoints(const COORDINATE_2D_STRU &stStartPoint, const COORDINATE_2D_STRU &stEndPoint, float deltaRadAbs, vector<COORDINATE_2D_STRU> &vectSamplePoints);

private:
    BOOL isValid_ = false;

    COORDINATE_2D_STRU stCenter_;
    float              radiusSqu_;

    BOOL               isExistRadius_;
    float              radius_;
};




#endif

